#include "opengl/opengl_buffer.h"

namespace engine
{
    VertexBuffer::VertexBuffer(const void *vertices, uint32_t size)
    {
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_STATIC_DRAW);
    }
    VertexBuffer::VertexBuffer(GLfloat *vertices, GLsizei size)
    {
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_STATIC_DRAW);
    }
    VertexBuffer::~VertexBuffer()
    {
        glDeleteBuffers(1, &vbo);
    }
    void VertexBuffer::bind()
    {
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
    }
    void VertexBuffer::unbind()
    {
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    void VertexBuffer::setData(uint32_t offset, uint32_t size, const void *data)
    {
        bind();
        glBufferSubData(GL_ARRAY_BUFFER, offset, size, data);
        unbind();
    }

    IndexBuffer::IndexBuffer(const uint32_t *indices, uint32_t size)
    {
        glGenBuffers(1, &ibo);
        glBindBuffer(GL_ARRAY_BUFFER, ibo);
        glBufferData(GL_ARRAY_BUFFER, size, indices, GL_STATIC_DRAW);
    }
    IndexBuffer::IndexBuffer(GLuint *indices, GLsizei size)
    {
        glGenBuffers(1, &ibo);
        glBindBuffer(GL_ARRAY_BUFFER, ibo);
        glBufferData(GL_ARRAY_BUFFER, size, indices, GL_STATIC_DRAW);
    }
    IndexBuffer::~IndexBuffer()
    {
        glDeleteBuffers(1, &ibo);
    }
    void IndexBuffer::bind()
    {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    }
    void IndexBuffer::unbind()
    {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    }

    VertexArray::VertexArray()
    {
        glGenVertexArrays(1, &vao);
        glBindBuffer(GL_ARRAY_BUFFER, vao);
    }
    VertexArray::~VertexArray()
    {
        glDeleteVertexArrays(1, &vao);
        for (int i = 0; i < vertexBuffers.size(); i++)
        {
            delete &vertexBuffers[i];
        }
    }
    void VertexArray::addVertexBuffer(VertexBuffer *buffer, GLint index, GLint length)
    {
        this->bind();
        buffer->bind();
        glVertexAttribPointer(index, length, GL_FLOAT, GL_FALSE, 0, (void *)0); // 每次只输入一种数据类型数组，不需要stride、offset切分
        glEnableVertexAttribArray(index);
        buffer->unbind();
        this->unbind();
        this->vertexBuffers.push_back(buffer);
    }
    void VertexArray::addIndexBuffer(IndexBuffer *buffer)
    {
        this->bind();
        buffer->bind();
        buffer->unbind();
        this->unbind();
        this->indexBuffers.push_back(buffer);
    }
    void VertexArray::bind()
    {
        glBindVertexArray(vao);
    }
    void VertexArray::unbind()
    {
        glBindVertexArray(0);
    }

    FrameBuffer::FrameBuffer()
    {
        glGenFramebuffers(1, &fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        // 生成纹理

        glGenTextures(1, &textureColor);
        glBindTexture(GL_TEXTURE_2D, textureColor);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glBindTexture(GL_TEXTURE_2D, 0);

        // 将它附加到当前绑定的帧缓冲对象
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColor, 0);

        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        {
            ENGINE_DEBUG("ERROR::FRAMEBUFFER:: Framebuffer is not complete!");
        }

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }
    FrameBuffer::~FrameBuffer()
    {
        glDeleteFramebuffers(1, &fbo);
    }
    void FrameBuffer::bind()
    {
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    }
    void FrameBuffer::unbind()
    {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }
    GLuint FrameBuffer::get_texture()
    {
        return textureColor;
    }

}
